package com.rock.pkp.impl;

import java.util.HashMap;



import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.rock.commonbo.api.ICommonBoService;
import com.rock.pkp.api.IPrimaryKeyService;
import com.rock.pkp.api.IRockKeytableService;
import com.rock.pkp.config.RockPKPConfig;
import com.rock.pkp.model.RockKeytable;
import com.rock.pkp.model.RockKeytableExample;

@Service
@Transactional
public class PrimaryKeyService implements IPrimaryKeyService {

	private static Logger log = LoggerFactory.getLogger(PrimaryKeyService.class);
	private static Map<String, ArrayBlockingQueue<Integer>> primaryKeyMap = new HashMap<String, ArrayBlockingQueue<Integer>>();
	@Autowired
	private IRockKeytableService rockKeytableService;
	@Autowired
	private ICommonBoService commonBoService;

	@Override
	public synchronized int getPrimaryKey(String tablename,String key) {
		if(key==null){
			key="id";
		}
		
		tablename = tablename.toLowerCase();// 转换为小写
		if (primaryKeyMap.containsKey(tablename)) {
			if (primaryKeyMap.get(tablename).size() == 0) {
				// 队列无数据则重新生成key列表
				if (generatorKey(tablename)) {
					return primaryKeyMap.get(tablename).poll();
				} else {
					log.error("--->重新生成表：" + tablename + "主键失败！");
					return 0;
				}
			} else {
				return primaryKeyMap.get(tablename).poll();
			}
		} else {
			System.out.println("========第一次初始化===================" + tablename);
			// 队列不存在则调用初始化方法
			if (initPrimaryKey(tablename,key)) {
				return getPrimaryKey(tablename,key);
			} else {
				log.error("--->初始化：" + tablename + "主键失败！");
				return 0;
			}
		}
	}

	/**
	 * 生成主键列表
	 * 
	 * @param tablename
	 *            表名
	 */
	private boolean generatorKey(String tablename) {
		RockKeytableExample example = new RockKeytableExample();
		example.or().andTablenameEqualTo(tablename);
		RockKeytable keyTable = rockKeytableService.selectFirstByExample(example);
		if (keyTable != null) {
			tablename = tablename.toLowerCase();
			primaryKeyMap.get(tablename).clear();
			int initKeyValue = keyTable.getKeyvalue();
			// 首先更新数据库的当前值
			keyTable.setKeyvalue(keyTable.getKeyvalue() + keyTable.getKeynum() * keyTable.getStep());
			int result = rockKeytableService.updateByPrimaryKey(keyTable);
			if (result != 0) {
				for (int i = 1; i <= keyTable.getKeynum(); i++) {
					primaryKeyMap.get(tablename).offer(initKeyValue + i * keyTable.getStep());// 加入队列
				}
				return true;
			} else {
				log.error("--->重新生成表：" + tablename + "主键失败，更新keytable表失败！");
				return false;
			}
		} else {
			log.error("--->重新生成表：" + tablename + "主键失败，未取得keytable表中对应的记录！");
			return false;
		}
	}

	/**
	 * 初始化主键队列 算法： 第1步：判断tablename在数据库中是否存在，存在则进行第2步，不存在则返回false<br>
	 * 第2步：判断tablename 在keytable中是否存在，存在则更新该表数据（keyvalue换为最大值），否则进行第3步<br>
	 * 第3步：获取tablename表中主键最大的值，数据库若没记录则最大值默认为配置文件初始值<br>
	 * 第4步：插入keytable表，keyvalue=最大值+（步长*配置文件的主键数量），keynum=配置数，step= 配置数 <br>
	 * 第5步：生成主键队列
	 * 
	 * @param tablename
	 *            表名
	 * @return 成功返回true，失败返回false <br>
	 */
	private boolean initPrimaryKey(String tablename,String key) {
		tablename = tablename.toLowerCase();// 转换为小写
		log.trace("--->初始化表：" + tablename + "主键===========begin=========");
		// 获取数据库
		// databaseType=PropertiesFileUtil.getInstance("rock-config").get("database.type");
		String databaseName = RockPKPConfig.getDatabaseName(); // PropertiesFileUtil.getInstance("rock-config").get("database.name");
		StringBuffer tableNameSql = new StringBuffer("select table_name from  INFORMATION_SCHEMA.TABLES WHERE table_schema ='");
		tableNameSql.append(databaseName + "'  and table_name ='" + tablename + "'");
		if (RockPKPConfig.getDatabaseType().equals("oracle")) {
			// oracle
			tableNameSql.delete(0, tableNameSql.length());
			tableNameSql.append("select table_name from dba_tables WHERE table_name ='");
			tableNameSql.append(tablename.toUpperCase() + "'");
		}
		List<?> list = commonBoService.query(tableNameSql.toString());
		if (list != null && list.size() > 0) {
			ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(RockPKPConfig.getPrimarykeyNum());// 队列长度为配置的主键数量
			primaryKeyMap.put(tablename, queue);// 初始化空队列map
			RockKeytableExample keyTableExample = new RockKeytableExample();
			keyTableExample.or().andTablenameEqualTo(tablename);
			RockKeytable upmsKeytable = rockKeytableService.selectFirstByExample(keyTableExample);
			if (upmsKeytable != null) {
				// 如果已经存在则更新记录
				if (updateKeytable(tablename,key)) {
					return generatorKey(tablename);// 重新生成主键队列
				} else {
					log.error("--->初始化表：" + tablename + "失败1");
					return false;
				}
			} else {
				// 不存在则初始化
				RockKeytable keyTableInit = new RockKeytable();
				keyTableInit.setTablename(tablename);
				keyTableInit.setKeyvalue(RockPKPConfig.getPrimarykeyInit());// 配置初始值
				keyTableInit.setStep(RockPKPConfig.getPrimarykeyStep());// 配置步长
				keyTableInit.setKeynum(RockPKPConfig.getPrimarykeyNum());// 配置数量
				int num = rockKeytableService.insertSelective(keyTableInit);
				if (num == 0) {
					log.error("--->初始化表：" + tablename + "失败2");
					return false;
				} else {
					return generatorKey(tablename);// 重新生成主键队列
				}
			}
		} else {
			log.error("--->初始化表：" + tablename + "主键失败，数据库中无此表！");
			return false;
		}
	}

	/**
	 * 更新主键表
	 * 
	 * @param tablename
	 * @return
	 */
	private boolean updateKeytable(String tablename,String key) {
		RockKeytableExample keyTableExample = new RockKeytableExample();
		keyTableExample.or().andTablenameEqualTo(tablename);
		RockKeytable kt = rockKeytableService.selectFirstByExample(keyTableExample);
		if (kt == null) {
			return false;
		} else {
			log.trace("=================tablename=====key======================================="+tablename+"============"+key);
			int keyvalue = commonBoService.getMaxId(tablename,key);
			if (keyvalue == 0) {
				// 数据库无数据时初始值为配置的初始值
				keyvalue = RockPKPConfig.getPrimarykeyInit();
			}
			kt.setKeyvalue(keyvalue);
			kt.setKeynum(RockPKPConfig.getPrimarykeyNum());//取配置
			kt.setStep(RockPKPConfig.getPrimarykeyStep());//取配置
			int result = rockKeytableService.updateByPrimaryKey(kt);
			if (result != 0) {
				return true;// 更新成功返回true
			} else {
				return false;
			}
		}
	}
}
